<template><div><h2 id="错误处理" tabindex="-1"><a class="header-anchor" href="#错误处理"><span>错误处理</span></a></h2>
<ul>
<li><a href="#introduction">介绍</a></li>
<li><a href="#configuration">配置</a></li>
<li><a href="#the-exception-handler">异常处理</a>
<ul>
<li><a href="#reporting-exceptions">异常报告</a></li>
<li><a href="#exception-log-levels">异常日志级别</a></li>
<li><a href="#ignoring-exceptions-by-type">忽略指定类型异常</a></li>
<li><a href="#rendering-exceptions">渲染异常</a></li>
<li><a href="#renderable-exceptions">Reportable &amp; Renderable 异常</a></li>
</ul>
</li>
<li><a href="#http-exceptions">HTTP 异常</a>
<ul>
<li><a href="#custom-http-error-pages">自定义 HTTP 错误页面</a></li>
</ul>
</li>
</ul>
<h2 id="介绍" tabindex="-1"><a class="header-anchor" href="#介绍"><span>介绍</span></a></h2>
<p>当你开始一个新的 Laravel 项目时，它已经为你配置了错误和异常处理。<code v-pre>App\Exceptions\Handler</code>类用于记录应用程序触发的所有异常，然后将其呈现回用户。我们将在本文中深入讨论这个类。</p>
<h2 id="配置" tabindex="-1"><a class="header-anchor" href="#配置"><span>配置</span></a></h2>
<p>你的<code v-pre>config/app.php</code>配置文件中的<code v-pre>debug</code>选项决定了对于一个错误实际上将显示多少信息给用户。默认情况下，该选项的设置将遵照存储在<code v-pre>.env</code>文件中的<code v-pre>APP_DEBUG</code>环境变量的值。</p>
<p>对于本地开发，你应该将<code v-pre>APP_DEBUG</code>环境变量的值设置为<code v-pre>true</code>。 <strong>在生产环境中，该值应始终为<code v-pre>false</code>。如果在生产中将该值设置为<code v-pre>true</code>，则可能会将敏感配置值暴露给应用程序的终端用户。</strong></p>
<h2 id="异常处理" tabindex="-1"><a class="header-anchor" href="#异常处理"><span>异常处理</span></a></h2>
<h3 id="异常报告" tabindex="-1"><a class="header-anchor" href="#异常报告"><span>异常报告</span></a></h3>
<p>所有异常都是由<code v-pre>App\Exceptions\Handler</code>类处理。此类包含一个<code v-pre>register</code>方法，可以在其中注册自定义异常报告程序和渲染器回调。我们将详细研究每个概念。异常报告用于记录异常或将其发送到如 <a href="https://flareapp.io/" target="_blank" rel="noopener noreferrer">Flare</a>、 <a href="https://bugsnag.com/" target="_blank" rel="noopener noreferrer">Bugsnag</a> 或 <a href="https://github.com/getsentry/sentry-laravel" target="_blank" rel="noopener noreferrer">Sentry</a> 等外部服务。默认情况下，将根据你的<a href="https://learnku.com/docs/laravel/10.x/logging" target="_blank" rel="noopener noreferrer">日志</a>配置来记录异常。不过，你可以用任何自己喜欢的方式来记录异常。</p>
<p>例如，如果您需要以不同的方式报告不同类型的异常，您可以使用 <code v-pre>reportable</code> 方法注册一个闭包，当需要报告给定的异常的时候便会执行它。 Laravel 将通过检查闭包的类型提示来判断闭包报告的异常类型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Exceptions<span class="token punctuation">\</span>InvalidOrderException</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 为应用程序注册异常处理回调</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">register</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">reportable</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">InvalidOrderException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>当您使用 <code v-pre>reportable</code> 方法注册一个自定义异常报告回调时， Laravel 依然会使用默认的日志配置记录下应用异常。 如果您想要在默认的日志堆栈中停止这个行为，您可以在定义报告回调时使用 stop 方法或者从回调函数中返回 <code v-pre>false</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">reportable</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">InvalidOrderException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token variable">$this</span><span class="token operator">-></span><span class="token function">reportable</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">InvalidOrderException</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>技巧</strong><br>
要为给定的异常自定义异常报告，您可以使用 <a href="https://learnku.com/docs/laravel/10.x/errors#renderable-exceptions" target="_blank" rel="noopener noreferrer">可报告异常</a>.</p>
</blockquote>
<h4 id="全局日志上下文" tabindex="-1"><a class="header-anchor" href="#全局日志上下文"><span>全局日志上下文</span></a></h4>
<p>在可用的情况下， Laravel 会自动将当前用户的编号作为数据添加到每一条异常日志信息中。您可以通过重写 <code v-pre>App\Exceptions\Handler</code> 类中的 <code v-pre>context</code> 方法来定义您自己的全局上下文数据（环境变量）。此后，每一条异常日志信息都将包含这个信息：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 获取默认日志的上下文变量。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;string, mixed></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token keyword">function</span> <span class="token function-definition function">context</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">return</span> <span class="token function">array_merge</span><span class="token punctuation">(</span><span class="token keyword static-context">parent</span><span class="token operator">::</span><span class="token function">context</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span></span>
<span class="line">        <span class="token string single-quoted-string">'foo'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'bar'</span><span class="token punctuation">,</span></span>
<span class="line">    <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="异常日志上下文" tabindex="-1"><a class="header-anchor" href="#异常日志上下文"><span>异常日志上下文</span></a></h4>
<p>尽管将上下文添加到每个日志消息中可能很有用，但有时特定的异常可能具有您想要包含在日志中的唯一上下文。通过在应用程序的自定义异常中定义<code v-pre>context</code>方法，您可以指定与该异常相关的任何数据，应将其添加到异常的日志条目中：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Exceptions</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Exception</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">InvalidOrderException</span> <span class="token keyword">extends</span> <span class="token class-name">Exception</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * 获取异常上下文信息</span>
<span class="line">     *</span>
<span class="line">     * <span class="token keyword">@return</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;string, mixed></span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">context</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">array</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'order_id'</span> <span class="token operator">=></span> <span class="token variable">$this</span><span class="token operator">-></span><span class="token property">orderId</span><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="report-助手" tabindex="-1"><a class="header-anchor" href="#report-助手"><span><code v-pre>report</code> 助手</span></a></h4>
<p>有时，您可能需要报告异常，但继续处理当前请求。<code v-pre>report</code>助手函数允许您通过异常处理程序快速报告异常，而无需向用户呈现错误页面：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">isValid</span><span class="token punctuation">(</span><span class="token keyword type-hint">string</span> <span class="token variable">$value</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">bool</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">try</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// Validate the value...</span></span>
<span class="line">    <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> <span class="token variable">$e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token function">report</span><span class="token punctuation">(</span><span class="token variable">$e</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="异常日志级别" tabindex="-1"><a class="header-anchor" href="#异常日志级别"><span>异常日志级别</span></a></h3>
<p>当消息被写入应用程序的<a href="https://learnku.com/docs/laravel/10.x/logging" target="_blank" rel="noopener noreferrer">日志</a>时，消息将以指定的<a href="https://learnku.com/docs/laravel/10.x/logging#log-levels" target="_blank" rel="noopener noreferrer">日志级别</a>写入，该级别指示正在记录的消息的严重性或重要性。</p>
<p>如上所述，即使使用<code v-pre>reportable</code>方法注册自定义异常报告回调，Laravel仍将使用应用程序的默认日志记录配置记录异常；但是，由于日志级别有时会影响消息记录的通道，因此您可能希望配置某些异常记录的日志级别。</p>
<p>为了实现这个目标，您可以在应用程序的异常处理程序的<code v-pre>$levels</code>属性中定义一个异常类型数组以及它们关联的日志级别：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">PDOException</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Psr<span class="token punctuation">\</span>Log<span class="token punctuation">\</span>LogLevel</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 包含其对应自定义日志级别的异常类型列表。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;class-string&lt;\Throwable>, \Psr\Log\LogLevel::*></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token variable">$levels</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token class-name static-context">PDOException</span><span class="token operator">::</span><span class="token keyword">class</span> <span class="token operator">=></span> <span class="token class-name static-context">LogLevel</span><span class="token operator">::</span><span class="token constant">CRITICAL</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="按类型忽略异常" tabindex="-1"><a class="header-anchor" href="#按类型忽略异常"><span>按类型忽略异常</span></a></h3>
<p>在构建应用程序时，您可能希望忽略某些类型的异常并永远不报告它们。应用程序的异常处理程序包含一个 <code v-pre>$dontReport</code> 属性，该属性初始化为空数组。您添加到此属性的任何类都将不会被报告；但是它们仍然可能具有自定义渲染逻辑：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Exceptions<span class="token punctuation">\</span>InvalidOrderException</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 不会被报告的异常类型列表。</span>
<span class="line"> *</span>
<span class="line"> * <span class="token keyword">@var</span> <span class="token class-name"><span class="token keyword">array</span></span>&lt;int, class-string&lt;\Throwable>></span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">protected</span> <span class="token variable">$dontReport</span> <span class="token operator">=</span> <span class="token punctuation">[</span></span>
<span class="line">    <span class="token class-name static-context">InvalidOrderException</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span></span>
<span class="line"><span class="token punctuation">]</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在内部，Laravel已经为您忽略了一些类型的错误，例如由404 HTTP错误或由无效CSRF令牌生成的419 HTTP响应引起的异常。如果您想指示Laravel停止忽略给定类型的异常，您可以在异常处理程序的<code v-pre>register</code>方法中调用<code v-pre>stopIgnoring</code>方法：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Symfony<span class="token punctuation">\</span>Component<span class="token punctuation">\</span>HttpKernel<span class="token punctuation">\</span>Exception<span class="token punctuation">\</span>HttpException</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * 为应用程序注册异常处理回调函数。</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">register</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">stopIgnoring</span><span class="token punctuation">(</span><span class="token class-name static-context">HttpException</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line">    <span class="token comment">// ...</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="渲染异常" tabindex="-1"><a class="header-anchor" href="#渲染异常"><span>渲染异常</span></a></h3>
<p>默认情况下，Laravel 异常处理程序会将异常转换为 HTTP 响应。但是，您可以自由地为给定类型的异常注册自定义渲染闭包。您可以通过在异常处理程序中调用<code v-pre>renderable</code>方法来实现这一点。</p>
<p>传递给 <code v-pre>renderable</code> 方法的闭包应该返回一个 <code v-pre>Illuminate\Http\Response</code> 实例，该实例可以通过 <code v-pre>response</code> 助手生成。 Laravel 将通过检查闭包的类型提示来推断闭包呈现的异常类型：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">App<span class="token punctuation">\</span>Exceptions<span class="token punctuation">\</span>InvalidOrderException</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * Register the exception handling callbacks for the application.</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">register</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">renderable</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">InvalidOrderException</span> <span class="token variable">$e</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">response</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">view</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'errors.invalid-order'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>您还可以使用 <code v-pre>renderable</code> 方法来覆盖内置的Laravel或Symfony异常的呈现行为，例如 <code v-pre>NotFoundHttpException</code>。如果传递给 <code v-pre>renderable</code> 方法的闭包没有返回值，则将使用Laravel的默认异常呈现：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Symfony<span class="token punctuation">\</span>Component<span class="token punctuation">\</span>HttpKernel<span class="token punctuation">\</span>Exception<span class="token punctuation">\</span>NotFoundHttpException</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * Register the exception handling callbacks for the application.</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">register</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token variable">$this</span><span class="token operator">-></span><span class="token function">renderable</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token class-name type-declaration">NotFoundHttpException</span> <span class="token variable">$e</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$request</span><span class="token operator">-></span><span class="token function">is</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'api/*'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line">            <span class="token keyword">return</span> <span class="token function">response</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">[</span></span>
<span class="line">                <span class="token string single-quoted-string">'message'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'Record not found.'</span></span>
<span class="line">            <span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">        <span class="token punctuation">}</span></span>
<span class="line">    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="reportable-renderable-异常" tabindex="-1"><a class="header-anchor" href="#reportable-renderable-异常"><span>Reportable &amp; Renderable 异常</span></a></h3>
<p>您可以直接在自定义异常类中定义 <code v-pre>report</code> 和 <code v-pre>render</code> 方法，而不是在异常处理程序的 <code v-pre>register</code> 方法中定义自定义报告和呈现行为。当存在这些方法时，框架将自动调用它们：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token php language-php"><span class="token delimiter important">&lt;?php</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">namespace</span> <span class="token package">App<span class="token punctuation">\</span>Exceptions</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Exception</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Request</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token keyword">use</span> <span class="token package">Illuminate<span class="token punctuation">\</span>Http<span class="token punctuation">\</span>Response</span><span class="token punctuation">;</span></span>
<span class="line"></span>
<span class="line"><span class="token keyword">class</span> <span class="token class-name-definition class-name">InvalidOrderException</span> <span class="token keyword">extends</span> <span class="token class-name">Exception</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * Report the exception.</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">void</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token doc-comment comment">/**</span>
<span class="line">     * Render the exception into an HTTP response.</span>
<span class="line">     */</span></span>
<span class="line">    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">render</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name return-type">Response</span></span>
<span class="line">    <span class="token punctuation">{</span></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">response</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果您的异常扩展了已经可呈现的异常，例如内置的Laravel或Symfony异常，则可以从异常的 <code v-pre>render</code> 方法中返回<code v-pre>false</code>，以呈现异常的默认HTTP响应：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * Render the exception into an HTTP response.</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">render</span><span class="token punctuation">(</span><span class="token class-name type-declaration">Request</span> <span class="token variable">$request</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token class-name">Response</span><span class="token operator">|</span><span class="token keyword type-declaration">bool</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token doc-comment comment">/** Determine if the exception needs custom rendering */</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token function">response</span><span class="token punctuation">(</span><span class="token comment">/* ... */</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果你的异常包含了只在特定条件下才需要使用的自定义报告逻辑，那么你可能需要指示 Laravel 有时使用默认的异常处理配置来报告异常。为了实现这一点，你可以从异常的 <code v-pre>report</code> 方法中返回 <code v-pre>false</code>：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token doc-comment comment">/**</span>
<span class="line"> * Report the exception.</span>
<span class="line"> */</span></span>
<span class="line"><span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">report</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token keyword return-type">bool</span></span>
<span class="line"><span class="token punctuation">{</span></span>
<span class="line">    <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token doc-comment comment">/** 确定异常是否需要自定义报告 */</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span>
<span class="line"></span>
<span class="line">        <span class="token comment">// ...</span></span>
<span class="line"></span>
<span class="line">        <span class="token keyword">return</span> <span class="token constant boolean">true</span><span class="token punctuation">;</span></span>
<span class="line">    <span class="token punctuation">}</span></span>
<span class="line"></span>
<span class="line">    <span class="token keyword">return</span> <span class="token constant boolean">false</span><span class="token punctuation">;</span></span>
<span class="line"><span class="token punctuation">}</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><blockquote>
<p><strong>注意</strong><br>
你可以在 <code v-pre>report</code> 方法中类型提示任何所需的依赖项，它们将自动被 Laravel 的<a href="https://learnku.com/docs/laravel/10.x/container" target="_blank" rel="noopener noreferrer">服务容器</a>注入该方法中。</p>
</blockquote>
<h2 id="http-异常" tabindex="-1"><a class="header-anchor" href="#http-异常"><span>HTTP 异常</span></a></h2>
<p>有些异常描述了服务器返回的 HTTP 错误代码。例如，这可能是一个 “页面未找到” 错误（404），一个 “未经授权错误”（401）或甚至是一个由开发者生成的 500 错误。为了从应用程序的任何地方生成这样的响应，你可以使用 <code v-pre>abort</code> 帮助函数：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token function">abort</span><span class="token punctuation">(</span><span class="token number">404</span><span class="token punctuation">)</span><span class="token punctuation">;</span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3 id="自定义-http-错误页面" tabindex="-1"><a class="header-anchor" href="#自定义-http-错误页面"><span>自定义 HTTP 错误页面</span></a></h3>
<p>Laravel 使得为各种 HTTP 状态码显示自定义错误页面变得很容易。例如，如果你想自定义 404 HTTP 状态码的错误页面，请创建一个 <code v-pre>resources/views/errors/404.blade.php</code> 视图模板。这个视图将会被渲染在应用程序生成的所有 404 错误上。这个目录中的视图应该被命名为它们对应的 HTTP 状态码。<code v-pre>abort</code> 函数引发的 <code v-pre>Symfony\Component\HttpKernel\Exception\HttpException</code> 实例将会以 <code v-pre>$exception</code> 变量的形式传递给视图：</p>
<div class="language-php line-numbers-mode" data-highlighter="prismjs" data-ext="php" data-title="php"><pre v-pre class="language-php"><code><span class="line"><span class="token operator">&lt;</span>h2<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token variable">$exception</span><span class="token operator">-></span><span class="token function">getMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">&lt;</span><span class="token operator">/</span>h2<span class="token operator">></span></span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>你可以使用 <code v-pre>vendor:publish</code> Artisan 命令发布 Laravel 的默认错误页面模板。一旦模板被发布，你可以根据自己的喜好进行自定义：</p>
<div class="language-bash line-numbers-mode" data-highlighter="prismjs" data-ext="sh" data-title="sh"><pre v-pre class="language-bash"><code><span class="line">php artisan vendor:publish <span class="token parameter variable">--tag</span><span class="token operator">=</span>laravel-errors</span>
<span class="line"></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h4 id="回退-http-错误页面" tabindex="-1"><a class="header-anchor" href="#回退-http-错误页面"><span>回退 HTTP 错误页面</span></a></h4>
<p>你也可以为给定系列的 HTTP 状态码定义一个“回退”错误页面。如果没有针对发生的具体 HTTP 状态码相应的页面，就会呈现此页面。为了实现这一点，在你应用程序的 <code v-pre>resources/views/errors</code> 目录中定义一个 <code v-pre>4xx.blade.php</code> 模板和一个 <code v-pre>5xx.blade.php</code> 模板。</p>
<blockquote>
<p>本译文仅用于学习和交流目的，转载请务必注明文章译者、出处、和本文链接<br>
我们的翻译工作遵照 <a href="https://learnku.com/docs/guide/cc4.0/6589" target="_blank" rel="noopener noreferrer">CC 协议</a>，如果我们的工作有侵犯到您的权益，请及时联系我们。</p>
</blockquote>
<hr>
<blockquote>
<p>原文地址：<a href="https://learnku.com/docs/laravel/10.x/errors/14857" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/10.x/er...</a></p>
<p>译文地址：<a href="https://learnku.com/docs/laravel/10.x/errors/14857" target="_blank" rel="noopener noreferrer">https://learnku.com/docs/laravel/10.x/er...</a></p>
</blockquote>
</div></template>


